﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Data.Framework;
using Microsoft.VisualStudio.Modeling;
using Liekhus.Xaf.BusinessObjectDesigner.CustomCode.DSRef;
using System.IO;
using System.Data;
using System.Data.SqlClient;

namespace Liekhus.Xaf.BusinessObjectDesigner
{
    public partial class LiekhusXafBusinessObjectDesignerDiagram
    {
        /// <summary>
        /// Initialize the drag/drop when the diagram is associated with a view (i.e. when
        /// a model is loaded from a file)
        /// </summary>
        protected override void OnAssociated(DiagramAssociationEventArgs e)
        {
            base.OnAssociated(e);

            // Ensure we have a view
            if (e.DiagramView == null || e.DiagramView.DiagramClientView == null)
            {
                return;
            }

            // Wireup the drag/drop support
            Control ctrl = e.DiagramView.DiagramClientView;
            ctrl.AllowDrop = true;
            ctrl.DragOver += OnDragOver;
            ctrl.DragDrop += OnDragDrop;
        }

        /// <summary>
        /// OnDragOver is used to inform OLE that the DiagramClientView associated with
        /// the current diagram is willing to accept the DSRef data format. Additionally,
        /// we enforce that only tables can be copied onto the diagram. We would
        /// normally do this in OnDragEnter as it's the appropriate event, but the
        /// DiagramClientView does not properly implement OnDragEnter by calling its
        /// base method (i.e. any event we wire up to DragEnter would never fire)
        /// </summary>
        private void OnDragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }

        /// <summary>
        /// OnDragDrop is used to create classes corresponding to the selection dragged
        /// from the Server Explorer
        /// </summary>
        private void OnDragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DSRefNavigator.DataSourceReferenceFormat))
            {
                try
                {
                    // Create a navigator for the DSRef Consumer (and dispose it when finished)
                    using (DSRefNavigator navigator = new DSRefNavigator(e.Data.GetData(DSRefNavigator.DataSourceReferenceFormat) as Stream))
                    {
                        string providerType = null;
                        IDbConnection dbInfo = ServerExplorerHelper.GetConnection(navigator, out providerType);

                        using (Transaction transaction = Model.Store.TransactionManager.BeginTransaction("Add Classes"))
                        {
                            foreach (DSRefNode node in navigator.ChildTableNodes)
                            {
                                DomainObject domainObject = new DomainObject(Store);
                                domainObject.Name = node.Name;
                                domainObject.BaseType = "XPLiteObject";
                                domainObject.TableName = string.Format("[{0}].[{1}]", node.Owner, node.Name);

                                IDataAdapter adapter = null;
                                if (dbInfo is SqlConnection)
                                {
                                    adapter = new SqlDataAdapter(string.Format("SELECT * FROM [{0}].[{1}] WHERE 1=0", node.Owner, node.Name), dbInfo as SqlConnection);
                                }

                                if (adapter != null)
                                {
                                    DataSet ds = new DataSet();
                                    adapter.FillSchema(ds, SchemaType.Source);
                                    DataTable table = ds.Tables[0];

                                    IList<string> keys = new List<string>();
                                    foreach (DataColumn column in table.PrimaryKey)
                                    {
                                        keys.Add(column.ColumnName);
                                    }

                                    foreach (DataColumn column in table.Columns)
                                    {
                                        DomainProperty property = new DomainProperty(Store);
                                        property.Name = column.ColumnName;
                                        property.ColumnName = column.ColumnName;
                                        property.PropertyType = column.DataType.Name;
                                        property.IsKeyProperty = keys.Contains(column.ColumnName);
                                        property.IsAutoGeneratedKey = property.IsKeyProperty;
                                        property.Size = column.MaxLength;
                                        property.IsUniqueValue = column.Unique;
                                        property.IsRequired = !column.AllowDBNull;
                                        domainObject.Properties.Add(property);
                                    }

                                    Model.Objects.Add(domainObject);
                                }
                            }

                            transaction.Commit();
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("Error retrieving table data.", ex);
                }

            }
        }

        private DomainModel Model
        {
            get
            {
                foreach (ModelElement element in Store.ElementDirectory.AllElements)
                {
                    if (element is DomainModel)
                        return (DomainModel)element;
                }

                return null;
            }
        }

    }
}
